home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / biblio / bibtex / utils / r2bib / r2bib.c < prev   
C/C++ Source or Header  |  1990-10-02  |  6KB  |  342 lines

  1. # include <ctype.h>
  2. # include <stdio.h>
  3.  
  4. struct rb {
  5.     char    rb_kl;        /* refer key letter        */
  6.     char *    rb_kw;        /* bibtex string        */
  7.     char    rb_emit;    /* don't print data if 0    */
  8.     char *    rb_data;    /* refer data            */
  9. };
  10.  
  11. struct rb rb[] = {
  12.     { 'A',    "author",    1,    NULL    },
  13.     { 'B',    "booktitle",    1,    NULL    },
  14.     { 'C',    "address",    1,    NULL    },
  15.     { 'D',    "year",        1,    NULL    },    /* mismatch */
  16.     { 'E',    "editor",    1,    NULL    },
  17. /*    { 'H',    "commentary1",    1,    NULL    },*/
  18.     { 'I',    "publisher",    1,    NULL    },
  19.     { 'J',    "journal",    1,    NULL    },
  20.     { 'K',    "note",        1,    NULL    },    /* mismatch */
  21.     { 'L',    "label",    0,    NULL    },    /* use as bibtex key */
  22.     { 'N',    "number",    1,    NULL    },
  23. /*    { 'O',    "commentary2",    1,    NULL    },*/
  24.     { 'P',    "pages",    1,    NULL    },
  25.     { 'Q',    "institution",    1,    NULL    },
  26.     { 'R',    "report",    0,    NULL    },
  27.     { 'S',    "series",    1,    NULL    },
  28.     { 'T',    "title",    1,    NULL    },
  29.     { 'V',    "volume",    1,    NULL    },
  30. /*    { 'X',    "abstract",    1,    NULL    },*/
  31.     { 0,    0,        0,    0    }
  32. };
  33.  
  34. struct bmap {
  35.     char    bm_kl;
  36.     char    *bm_entry;
  37. };
  38.  
  39. /*
  40.  * entries are in order of precedence.
  41.  * any entry with a 'J' field must be
  42.  * an article, but anthing with an 'I'
  43.  * field doesn't have to be a book (if
  44.  * an entry has both 'J' and 'I' it is
  45.  * considered to be an article).
  46.  */
  47. struct bmap    bmap[] = {
  48.     { 'J',    "article"    },
  49.     { 'R',    "techreport"    },
  50.     { 'I',    "book"        },
  51.     { 0,    0        }
  52. };
  53.  
  54. main(argc, argv)
  55.     char        **argv;
  56. {
  57.     register FILE    *fid;
  58.     register int    i;
  59.     int        err;
  60.  
  61.     err = 0;
  62.  
  63.     if (argc > 1) {
  64.         for (i = 1; i < argc; i++) {
  65.             if ((fid = fopen(argv[i], "r")) == NULL) {
  66.                 fprintf(stderr, "fopen: ");
  67.                 perror(argv[i]);
  68.                 continue;
  69.             }
  70.             err += r2bib(argv[i], fid);
  71.         }
  72.     }
  73.     else
  74.         err += r2bib("stdin", stdin);
  75.  
  76.     if (err)
  77.         exit(1);
  78.  
  79.     exit(0);
  80. }
  81.  
  82. r2bib(file, fid)
  83.     char        *file;
  84.     FILE        *fid;
  85. {
  86.     extern char    *sanz();
  87.     register char    *cp;
  88.     struct rb    *lrb;        /* last rb stored into */
  89.     int        line;
  90.     char        buf[BUFSIZ];
  91.     int        err;
  92.  
  93.     lrb = NULL;
  94.     err = 0;
  95.     line = 0;
  96.  
  97.     while (fgets(buf, sizeof(buf), fid) != NULL) {
  98.         line++;
  99.  
  100.         if ((cp = sanz(buf)) == NULL) {
  101.             if (lrb != NULL) {
  102.                 dumprb();
  103.                 lrb = NULL;
  104.             }
  105.             continue;
  106.         }
  107.  
  108.         /*
  109.          * if the first letter is a % then it's the
  110.          * a new record, otherwise it's a continuation
  111.          * of the previous one.
  112.          */
  113.         if (cp[0] == '%') {
  114.             for (lrb = &rb[0]; lrb->rb_kl != 0; lrb++) {
  115.                 if (lrb->rb_kl == cp[1]) {
  116.                     stuffrb(lrb, &cp[2]);
  117.                     break;
  118.                 }
  119.             }
  120.             if (lrb->rb_kl == 0) {
  121.                 fprintf(stderr, "r2b: %s: line %d: unknown key letter %c, ignoring\n", file, line, cp[1]);
  122.                 err = 1;
  123.             }
  124.         }
  125.         else {
  126.             if (lrb == NULL) {
  127.                 fprintf(stderr, "r2b: %s: line %d: bad format, ignoring\n", file, line);
  128.                 err = 1;
  129.                 continue;
  130.             }
  131.  
  132.             stuffrb(lrb, &cp[0]);
  133.         }
  134.     }
  135.  
  136.     if (lrb != NULL)
  137.         dumprb();
  138.  
  139.     return(err);
  140. }
  141.  
  142. dumprb() {
  143.     register struct rb    *trb;
  144.     register struct bmap    *bm;
  145.     static int        key;
  146.     char            *bibkey;
  147.     char            *cp;
  148.     int            first;
  149.  
  150.     /*
  151.      * first, figure out what type of entry this
  152.      * is.
  153.      */
  154.     for (bm = &bmap[0]; bm->bm_kl != 0; bm++) {
  155.         for (trb = &rb[0]; trb->rb_kl != 0; trb++) {
  156.             if ((trb->rb_kl == bm->bm_kl) && (trb->rb_data != NULL)) {
  157.                 printf("@%s{", bm->bm_entry);
  158.                 goto out;
  159.             }
  160.         }
  161.     }
  162. out:
  163.     if (bm->bm_kl == 0)
  164.         printf("@misc{");
  165.  
  166.     /*
  167.      * in order of precedence; how to determine the
  168.      * bibtex key:
  169.      *    1. use keyword (%K) if only one word.
  170.      *    2. use refer label (%L).
  171.      *    3. otherwise just use the string "keyN" where N
  172.      *       is the count of this bibliographic entry in
  173.      *       the refer file.
  174.      */
  175.     key++;
  176.     for (trb = &rb[0]; trb->rb_kl != 0; trb++) {
  177.         if ((trb->rb_kl == 'K') && (trb->rb_data != NULL)) {
  178.             for (cp = trb->rb_data; *cp != NULL; cp++) {
  179.                 if (isspace(*cp))
  180.                     break;
  181.             }
  182.  
  183.             /* ran to end of string? */
  184.             if (*cp == NULL) {
  185.                 printf("%s,\n", trb->rb_data);
  186.  
  187.                 /* if used here then free & zero it */
  188.                 (void) free(trb->rb_data);
  189.                 trb->rb_data = NULL;
  190.                 break;
  191.             }
  192.         }
  193.  
  194.         if ((trb->rb_kl == 'L') && (trb->rb_data != NULL)) {
  195.             for (cp = trb->rb_data; *cp != NULL; cp++) {
  196.                 if (isspace(*cp))
  197.                     break;
  198.             }
  199.  
  200.             /* ran to end of string? */
  201.             if (*cp == NULL) {
  202.                 printf("%s,\n", trb->rb_data);
  203.                 break;
  204.             }
  205.         }
  206.     }
  207.  
  208.     /* nothing reasonable to use, punt */
  209.     if (trb->rb_kl == 0)
  210.         printf("key%d,\n", key);
  211.  
  212.     first = 1;
  213.  
  214.     for (trb = &rb[0]; trb->rb_kl != 0; trb++) {
  215.         if (trb->rb_data == NULL)
  216.             continue;
  217.  
  218.         if (trb->rb_emit != 0) {
  219.             /*
  220.              * clank,
  221.              * this is so that things will line up.
  222.              */
  223.             if (strlen(trb->rb_kw) < 6)
  224.                 cp = "\t\t";
  225.             else
  226.                 cp = "\t";
  227.  
  228.             if (! first)
  229.                 printf(",\n");
  230.  
  231.             printf("\t%s =%s\"%s\"", trb->rb_kw, cp, trb->rb_data);
  232.             first = 0;
  233.         }
  234.  
  235.         (void) free(trb->rb_data);
  236.         trb->rb_data = NULL;
  237.     }
  238.  
  239.     printf("\n}\n\n");
  240. }
  241.  
  242. stuffrb(lrb, cp)
  243.     struct rb    *lrb;
  244.     char        *cp;
  245. {
  246.     extern char    *andfix();
  247.     extern char    *malloc();
  248.     extern char    *realloc();
  249.  
  250.     /* empty data field */
  251.     if ((cp = sanz(cp)) == NULL)
  252.         return;
  253.  
  254.     if (lrb->rb_kl == 'A')
  255.         cp = andfix(cp);
  256.  
  257.     if (lrb->rb_data == NULL) {
  258.         if ((lrb->rb_data = malloc(strlen(cp) + 1)) == NULL) {
  259.             perror("malloc");
  260.             exit(1);
  261.         }
  262.  
  263.         strcpy(lrb->rb_data, cp);
  264.     }
  265.     else {
  266.         char    *conj;
  267.  
  268.         if (lrb->rb_kl == 'A')
  269.             conj = " and ";
  270.         else
  271.             conj = " ";
  272.  
  273.         if ((lrb->rb_data = realloc(lrb->rb_data, strlen(lrb->rb_data) + strlen(cp) + strlen(conj) + 1)) == NULL) {
  274.             perror("realloc");
  275.             exit(1);
  276.         }
  277.  
  278.         strcat(lrb->rb_data, conj);
  279.         strcat(lrb->rb_data, cp);
  280.     }
  281. }
  282.  
  283. /*
  284.  */
  285. char *
  286. andfix(string)
  287.     register char    *string;
  288. {
  289.     register char    *tmp;
  290.     register char    *cp;
  291.  
  292.     tmp = string;
  293.  
  294.     for (cp = string; *cp != NULL; cp++) {
  295.         if (strncmp(cp, " and ", 5) == 0) {
  296.             /*
  297.              * +2 for the curly braces around "{and}",
  298.              * +1 for the null at the end.
  299.              */
  300.             if ((tmp = malloc(strlen(string) + 2 + 1)) == NULL) {
  301.                 perror("malloc");
  302.                 exit(1);
  303.             }
  304.  
  305.             strncpy(tmp, string, cp - string);
  306.             tmp[cp - string] = NULL; /* strncpy doesn't */
  307.             strcat(tmp, " {and} ");
  308.             strcat(tmp, cp + 5);
  309.         }
  310.     }
  311.  
  312.     return(tmp);
  313. }
  314.  
  315. char *
  316. sanz(bp)
  317.     char        *bp;
  318. {
  319.     register char    *cp;
  320.  
  321.     cp = &bp[strlen(bp) - 1];
  322.  
  323.     /*
  324.      * back up over any spaces chars
  325.      */
  326.     while (isspace(*cp) && (cp >= bp))
  327.         cp--;
  328.  
  329.     if (cp < bp)
  330.         return(NULL);    /* empty line */
  331.  
  332.     *++cp = NULL;
  333.  
  334.     while (isspace(*bp) && (bp < cp))
  335.         bp++;
  336.  
  337.     if (cp == bp)
  338.         return(NULL);    /* empty line */
  339.  
  340.     return(bp);
  341. }
  342.